package com.example.demo.util;

import org.jooq.Record;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * @author 邓凯献
 *         create 17-12-8
 *         description: 类属性操作工具类
 */
public class ClazzUtils {
    /**
     * @param source 原数据
     * @param target 目标
     * @throws NoSuchMethodException
     * @throws SecurityException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     */
    public static void copy(Object source, Object target) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Class sourceClass = source.getClass();//得到对象的Class
        Class targetClass = target.getClass();//得到对象的Class

        Field[] sourceFields = sourceClass.getDeclaredFields();//得到Class对象的所有属性
        Field[] targetFields = targetClass.getDeclaredFields();//得到Class对象的所有属性

        for (Field sourceField : sourceFields) {
            String name = sourceField.getName();//属性名
            Class type = sourceField.getType();//属性类型

            String methodName = name.substring(0, 1).toUpperCase() + name.substring(1);

            Method getMethod = sourceClass.getMethod("get" + methodName);//得到属性对应get方法

            Object value = getMethod.invoke(source);//执行源对象的get方法得到属性值

            if (!AssertUtils.isNotNull(value)) {
                continue;
            }
            for (Field targetField : targetFields) {
                String targetName = targetField.getName();//目标对象的属性名

                if (targetName.equals(name)) {
                    Method setMethod = targetClass.getMethod("set" + methodName, type);//属性对应的set方法

                    setMethod.invoke(target, value);//执行目标对象的set方法
                }
            }
        }
    }



    /**
     *根据属性名获取属性值
     * @param fieldName 字段名称
     * @param o　对象
     * @return  Object
     */
    public static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[] {});
            return value;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     *获取CLASS属性数组
     *@param clazz 类class
     */
    public static Field[] getFileds(Class clazz){
        try {
            return  clazz.getDeclaredFields();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     *获取CLASS属性数组
     * @param clazz 类class
     */
    public static List<Field> getFiledList(Class clazz){
        try {
            return Arrays.asList(clazz.getDeclaredFields());
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 根据属性名设置属性值
     *
     * @param fieldName 字段名称
     * @param o         　对象
     * @return Object
     */
    public void setFieldValueByName(String fieldName, String value, Object o) {
        try {
            PropertyDescriptor pd = new PropertyDescriptor(fieldName,
                    o.getClass());
            Method setMethod = pd.getWriteMethod();//获得set方法
            String xclass = setMethod.getParameterTypes()[0].toString();
            if (xclass.equals("class java.lang.String")) {
                setMethod.invoke(o, value);
            } else if (xclass.equals("class java.util.Date")) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                setMethod.invoke(o, sdf.parse(value));
            } else if (xclass.equals("class java.lang.Boolean")) {
                Boolean boolname = true;
                if (value.equals("false")) {
                    boolname = false;
                }
                setMethod.invoke(o, boolname);
            } else if (xclass.equals("class java.lang.Integer")) {
                setMethod.invoke(o, new Integer(value));
            } else if (xclass.equals("class java.lang.Long")) {
                setMethod.invoke(o, new Long(value));
            } else if (xclass.equals("class java.math.BigDecimal")) {
                setMethod.invoke(o, new BigDecimal(value));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取CLASS属性数组
     *
     * @param o 类class
     */
    public void copyRecordValueToObject(Object o, Record record) {
        try {
            org.jooq.Field[]  fields2 = record.fields();

            System.out.println(fields2[0].getName());;

            List<Field> fields = this.getFiledList(o.getClass());
            if(AssertUtils.isNotEmpty(fields) && AssertUtils.isNotNull(record)){
                fields.forEach(field -> {
                    Arrays.stream(record.fields()).filter(recordField -> recordField.getName().equals(field.getName())).findFirst().ifPresent(recordField -> {
                        Object value = record.getValue(recordField.getName());
                        if(AssertUtils.isNotNull(value)){
                            this.setFieldValueByName(field.getName(),value+"",o);
                        }
                    });
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 将一个对象的非空属性复制到另一个对象
     *
     * @param source 源对象
     * @param target 目标对象
     */
    public static void copyPropertiesIgnoreNull(Object source, Object target) {
        try {
            Class<?> sourceClass = source.getClass();
            Field[] sourceFields = sourceClass.getDeclaredFields();
            Field[] sourceSuperFields = sourceClass.getSuperclass().getDeclaredFields();
            List<Field> sourceFieldList = new ArrayList();
            sourceFieldList.addAll(Arrays.asList(sourceFields));
            sourceFieldList.addAll(Arrays.asList(sourceSuperFields));
            Class<?> targetClass = target.getClass();
            Field[] targetFields = targetClass.getDeclaredFields();
            Field[] targetSuperFields = targetClass.getSuperclass().getDeclaredFields();
            List<Field> targetFieldList = new ArrayList();
            targetFieldList.addAll(Arrays.asList(targetFields));
            targetFieldList.addAll(Arrays.asList(targetSuperFields));
            Iterator var10 = targetFieldList.iterator();
            while(var10.hasNext()) {
                Field tf = (Field)var10.next();
                tf.setAccessible(true);
                Iterator var12 = sourceFieldList.iterator();
                while(var12.hasNext()) {
                    Field sf = (Field)var12.next();
                    sf.setAccessible(true);
                    if (!Modifier.isStatic(sf.getModifiers()) && !Modifier.isStatic(tf.getModifiers())
                            && tf.getName().equals(sf.getName()) && sf.get(source) != null && !"".equals(sf.get(source))
                            && tf.getType().equals(sf.getType())) {
                        tf.set(target, sf.get(source));
                    }
                }
            }
        } catch (IllegalAccessException var14) {
            var14.printStackTrace();
        }

    }

    /**
     * 将一个对象的非空属性复制到另一个对象
     *
     * @param source 源对象
     * @param target 目标对象
     */
    public static void copyProperties(Object source, Object target) {
        try {
            Class<?> sourceClass = source.getClass();
            Field[] sourceFields = sourceClass.getDeclaredFields();
            Field[] sourceSuperFields = sourceClass.getSuperclass().getDeclaredFields();
            List<Field> sourceFieldList = new ArrayList();
            sourceFieldList.addAll(Arrays.asList(sourceFields));
            sourceFieldList.addAll(Arrays.asList(sourceSuperFields));
            Class<?> targetClass = target.getClass();
            Field[] targetFields = targetClass.getDeclaredFields();
            Field[] targetSuperFields = targetClass.getSuperclass().getDeclaredFields();
            List<Field> targetFieldList = new ArrayList();
            targetFieldList.addAll(Arrays.asList(targetFields));
            targetFieldList.addAll(Arrays.asList(targetSuperFields));
            Iterator var10 = targetFieldList.iterator();
            while(var10.hasNext()) {
                Field tf = (Field)var10.next();
                tf.setAccessible(true);
                Iterator var12 = sourceFieldList.iterator();
                while(var12.hasNext()) {
                    Field sf = (Field)var12.next();
                    sf.setAccessible(true);
                    if (!Modifier.isStatic(sf.getModifiers()) && !Modifier.isStatic(tf.getModifiers())
                            && tf.getName().equals(sf.getName())
                            && tf.getType().equals(sf.getType())) {
                        tf.set(target, sf.get(source));
                    }
                }
            }
        } catch (IllegalAccessException var14) {
            var14.printStackTrace();
        }
    }
    /**
     * 判断一个类是否实现了某个接口
     * @param target
     * @param interfaceClass
     * @return
     */
    public static boolean isImplement(Class<?> target, Class<?> interfaceClass){
        for (Class<?> i : target.getInterfaces()){
            if(i == interfaceClass){
                return true;
            }
            if(i.getInterfaces().length > 0){
                isImplement(i, interfaceClass);
            }
        }
        Class<?> superclass = target.getSuperclass();
        if(superclass != null){
            return isImplement(superclass, interfaceClass);
        }
        return false;
    }
}